﻿using System;
using Myotragus.Data.Containers;

namespace Myotragus.Data.Repositories
{
	/// <summary>
	/// A service that provides persistence operations for an entity.
	/// </summary>
	/// <remarks>
	/// The use of providers should be through a <see cref="IServicesContainer"/>. Providers should be
	/// thread safe, as they'd be singleton and would handle many requests.
	/// <example>
	///	 var repository = container.ResolveService&lt;ITableProvider&gt();
	///	 var table = repository.New(new {Name = "Table1", Created = DateTime.Now});
	///	 repository.Save(table) ;
	/// </example>
	/// Interfaces and extension methods with basic read/write operations have been implemented (
	/// <see cref="IWriteRepository{TEntity}"/> and
	/// <see cref="IReadRepository{TEntity}"/>).
	///
	/// A repository implementation, with basic read write operations would be like:
	/// <example>
	///	 interface ITableProvider : IRepository&lt;ITable&gt;, IReadProvider&lt;ITable&gt;,
	///	 IWriteProvider&lt;ITable&gt;	{}
	///	 class TableProvider : repository&lt;ITable&gt;, ITableProvider {}
	/// </example>
	/// No code would be necesary inside neither <code>ITableProvider</code> nor <code>IWriteProvider</code>.
	///
	/// To include additional functionalities to a repository you could either, use extension or instance
	/// methods.
	/// </remarks>
	public interface IRepository : IService
	{
		/// <summary>
		/// Actual implementation for current service entity.
		/// </summary>
		Type EntityImplementation { get; }
	}

	/// <summary>
	/// A service that provides persistence operations for an entity.
	/// </summary>
	/// <typeparam name="TEntity">Entity type, strongly recomended the use of interfaces only.</typeparam>
	public interface IRepository<TEntity> : IRepository
	{
		/// <summary>
		/// Creates a new Entity. Implementations should relay on <see cref="IEntitiesContainer.Create{TEntity}()"/>
		/// </summary>
		/// <returns>New entity instance</returns>
		TEntity New();

		/// <summary>
		/// Creates a new Entity and initializes it with matching properties from a prototype object.
		/// Implementations should relay on <see cref="IEntitiesContainer.Create{TEntity}(object)"/>
		/// </summary>
		/// <returns>New entity instance</returns>
		TEntity New(object prototype);
	}
}